#include <algorithm>
//B#include <cassert>
#include <cstdlib>
#include <fstream>
#include <string>
#include <vector> 


#include "Config.h"
#include <Support\Log.h>
#include <Support\GAssert.h>

using namespace std;

Config Config::theInstance;

bool Config::loadConfigFile(const char* configurationFile)
{

	if (NULL == configurationFile || nullptr == configurationFile)
		return false;

	std::ifstream inStream(configurationFile);
	if (! inStream.is_open())
		return false;

	string line;
	while(getline (inStream,line))
	{
		std::size_t found = line.find("=");
		if (found == std::string::npos)
			continue;

		ASSERT(numOptions < NUM_MAX_OPTIONS, 
			"Configuration Options already used, numoptions < NUM_MAX_OPTIONS  %d < %d",
			numOptions, NUM_MAX_OPTIONS);

		string configOption = line.substr (0,found);
		string configValue = line.substr (found+1);

		configOption = configOption.substr(configOption.find_first_not_of(" \t"));
		configValue = configValue.substr(configValue.find_first_not_of(" \t"));

		configOption = configOption.substr(0, configOption.find_last_not_of(" \t")+1);
		configValue = configValue.substr(0, configValue.find_last_not_of(" \t")+1);

		std::transform(configOption.begin(), configOption.end(), configOption.begin(), tolower);
		std::transform(configValue.begin(), configValue.end(), configValue.begin(), tolower);

		uint updateAt = numOptions;
		for(uint i = 0; i < numOptions; i++)
		{
			string s(configOptions[i].configName);
			if (s == configOption )
				updateAt = i;
		}
		if (updateAt == numOptions)
		{
			numOptions++;
			strcpy_s((char*)configOptions[updateAt].configName, 
				sizeof(configOptions[updateAt].configName), configOption.c_str());
		}
		strcpy_s((char*)configOptions[updateAt].configValue, 
			sizeof(configOptions[updateAt].configValue), configValue.c_str());
	}
	inStream.close();
	return true;
}
		
void Config::loadDefaultConfig()
{
	// just lowercases!!!!!!!!!!!!!!!
	char* configOptionsData[] = {
	"logfile","none",
	"storagemanager","32M",
	"","",
	"","",
	};

	for(numOptions = 0; numOptions < NUM_MAX_OPTIONS; numOptions++)
	{
		if (strcmp("", configOptionsData[numOptions*2]) == 0)
			break;

		strcpy_s((char*)configOptions[numOptions].configName, 
			sizeof(configOptions[numOptions].configValue), configOptionsData[2*numOptions]);
		strcpy_s((char*)configOptions[numOptions].configValue, 
			sizeof(configOptions[numOptions].configValue), configOptionsData[2*numOptions + 1]);
	}
}

Config& Config::getInstance()
{
	return theInstance;
}

const char* Config::getOptionString(const char* option)
{
	if (! isInitialized)
		return NULL;

	for(uint i = 0; i < numOptions; i++)
		if (! strcmp(configOptions[i].configName, option))
			return configOptions[i].configValue;
	return NULL;
}

void Config::getConfigureOptions(std::string& options)
{
	options.clear();
	if (!isInitialized)
		return;

	for(uint i = 0; i < numOptions; i++)
	{
		options += configOptions[i].configName;
		options += " = ";
		options += configOptions[i].configValue;
		options += "\n";
	}
	options += "End of Configuration";
}

bool Config::initialize(const char* configurationFile, bool quiet)
{
	if (isInitialized)
		return true;

	quietMode = quiet;

	static const char* welcomeMessage = "Config Manager Started...";
	if (! quietMode)
		gLog(welcomeMessage);

	isInitialized = true;

	loadDefaultConfig();
	if (NULL == configurationFile)
		return true;
	return loadConfigFile(configurationFile);
}

bool Config::shutdown()
{
	isInitialized = false;
	static const char* finalMessage = "Config Manager Shutting down...";
	if (! quietMode)
		gLog(finalMessage);
	return true;
}